package com.sohu.tv.controller;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.sohu.tv.cache.RedisDao;
import com.sohu.tv.entity.AcountEnum;
import com.sohu.tv.entity.App;
import com.sohu.tv.entity.User;
import com.sohu.tv.service.AppService;
import com.sohu.tv.service.UserService;
import com.sohu.tv.utils.CookieTool;
import com.sohu.tv.utils.OAuthUtil;
import com.sohu.tv.utils.SecretUtil;
/***
 * oauth2 服务协议
 * @author YunLong
 *
 */
@Controller
@RequestMapping(value="/oauth2")
public class ServerController{
	
	private Logger logger = LoggerFactory.getLogger(this.getClass());
	
	@Resource
	AppService appService;
	@Resource
	RedisDao redisDao;
	@Resource
	UserService userService;
	
	/**
	 * 生成code
	 * @param appid 授权应用ID
	 * @param redirect_uri 授权成功回调地址
	 * @param response_type	请求类型
	 * @param state	请求参数
	 * @return code	返回code凭证
	 */
	@RequestMapping(value="/authorize",method=RequestMethod.POST)
	public String getCode(String appid,String redirect_uri,String response_type,
						  String state,HttpServletResponse response,HttpServletRequest request,Model model){
		//应用必要参数是否合法
		if("".equals(appid) || "".equals(redirect_uri) || "".equals(response_type)){
			model.addAttribute("msg", "应用认证失败！");
			return "user/fail";
		}
		boolean isLegal = false;
		//获取COOKIE存储在MAP中
		Map<String,String> cookies = CookieTool.ReadCookieMap(request);
		String loginSign = cookies.get("pt_login_sign");
		String timeout = cookies.get("pt_time");
		String acount = cookies.get("pt_acount");
		//判断COOKIE是否有效
		if(loginSign == null || timeout == null || acount == null){
			model.addAttribute("appid", appid);
			model.addAttribute("redirect_uri", redirect_uri);
			return "user/login";
		}
		//检查COOKIE是否合法
		String legalSign = SecretUtil.getMD5(SecretUtil.decodeBase64(acount), AcountEnum.KEY.toString());
		if(legalSign.equals(loginSign)){
			//检查COOKIE时间是否过期
			Date date = new Date();
			long current = date.getTime();
			long interval = current - Long.valueOf(timeout);
			if(interval/1000 < Long.valueOf(AcountEnum.TIMEOUT.toString())){
				//再次校验用户是否合法
				User user = userService.queryByName(SecretUtil.decodeBase64(acount));
				if(user != null){
					isLegal = true;
				}
			}
			//COOKIE信息错误
			if(!isLegal){
				return "user/login";
			}
		}
		//COOKIE信息校验通过,判断应用是否具有授权资格
		if(isLegal && !"".equals(appid)){
			App app = appService.getById(appid);
			if(null != app && "code".equals(response_type)){
				//生成 32 位随机不重复 code，并且跳转到 redirect_uri
				String code = OAuthUtil.code(32);
				//将 code 存储到 redis 中，过期时间为 300s
				redisDao.setCode(code, Integer.valueOf(AcountEnum.CODETIME.toString()));
				//设置回调地址参数
				redirect_uri = redirect_uri + "?code=" + code +"&state=" + acount;
				logger.info("code is : {}", code);
				// 302 重定向到回调地址
				return "redirect:" + redirect_uri;
			}
			//认证失败
			model.addAttribute("msg", "应用认证失败！");
			return "user/fail";
		}
		//获取 code 失败
		model.addAttribute("msg", "应用认证失败！");
		return "user/fail";
	}
	
	/**
	 * 通过code获取token
	 * @param appid 应用ID
	 * @param secret 应用秘钥
	 * @param code code:换取token的票据
	 * @param grant_type 固定值：authorization_code
	 * @return token
	 */
	@RequestMapping(value="/access_token",method=RequestMethod.GET)
	@ResponseBody
	public Map<String,Object> getToken(String appid,String secret,String code,String grant_type,String state){
		Map<String,Object> result = new HashMap<String,Object>();
		if(!"".equals(appid)){
			App app = appService.getById(appid);
			if(null != app && "authorization_code".equals(grant_type)){
				//从redis中获取code
				String aliveCode = redisDao.getCode(code);
				//验证code与应用秘钥secret是否相等
				if(secret.equals(app.getAppSecret()) && code.equals(aliveCode)){
					//删除code，保证只能使用一次
					redisDao.delCode(aliveCode);
					//授权成功，返回openId以及token
					String token = OAuthUtil.accessToken();
					//再次检验用户是否合法
					String username = SecretUtil.decodeBase64(state);
					User  user = userService.queryByName(username);
					String openId = "";
					if(user != null){
						//相同用户生成openId一致
						openId = OAuthUtil.openId(user.getUserId(), appid);
						//将token存入redis中，openId作为唯一的key值,设置token有效时间为7200s
						redisDao.setToken(openId, Integer.valueOf(AcountEnum.TOKENTIME.toString()),token,user.getUserId());
						result.put("openid", openId);
						result.put("access_token", token);
						result.put("CODE", 200);
						logger.info("授权成功! openId : {},token : {}",openId,token);
						return result;
					}
					//授权失败，返回错误代码-1
					result.put("CODE", -1);
					result.put("openid", "");
					return result;
				}
			}
		}
		//授权失败，返回错误代码-1
		result.put("CODE", -1);
		result.put("openid", "");
		return result;
	}
	
	/**
	 * 用户名密码验证
	 * @param username 账号
	 * @param password 密码
	 * @return
	 */
	@RequestMapping(value="/login",method=RequestMethod.POST)
	public String login(String username,String password,String appid,String redirect_uri,
						HttpServletResponse response,Model model){
		if("".equals(appid) || "".equals(redirect_uri)){
			model.addAttribute("msg", "应用认证失败！");
			return "user/fail";
		}
		
		if("".equals(username) || "".equals(password)){
			model.addAttribute("msg", "用户名或密码不能为空！");
			model.addAttribute("appid", appid);
			model.addAttribute("redirect_uri", redirect_uri);
			return "user/login";
		}
		//获取第三方应用信息
		App app = appService.getById(appid);
		//第三方应用未认证
		if(app == null){
			model.addAttribute("msg", "应用认证失败！");
			model.addAttribute("appid", appid);
			model.addAttribute("redirect_uri", redirect_uri);
			return "user/fail";
		}
		//验证用户名与密码
		User user = userService.queryByUserPass(username, password);
		//用户名密码校验
		if(user != null){
			//用户名密码验证通过，显示授权页面
			Date time = new Date();
			//使用MD5对账号签名加密
			String acount = SecretUtil.getMD5(username, AcountEnum.KEY.toString());
			String timeout = time.getTime() + "";
			CookieTool.addCookie(response, "pt_login_sign", acount , 60*30);
			//设置时间戳
			CookieTool.addCookie(response, "pt_time", timeout , 60*30);
			//设置账号信息,使用Base64编码加密
			CookieTool.addCookie(response, "pt_acount", SecretUtil.encodeBase64(username) , 60*30);
			model.addAttribute("appid", appid);
			model.addAttribute("redirect_uri", redirect_uri);
			model.addAttribute("response_type", "code");
			return "user/authorize";
		}
		//验证失败，返回到登录页面
		model.addAttribute("msg", "用户名或密码错误!");
		model.addAttribute("appid", appid);
		model.addAttribute("redirect_uri", redirect_uri);
		return "user/login";
	}
	/**
	 * 授权页面显示
	 * @param appid	申请应用ID
	 * @param redirect_uri 回调地址
	 * @param request_type 请求类型	
	 * @return
	 */
	@RequestMapping(value="/show")
	public String show(String appid,String request_type,String redirect_uri,
					   HttpServletRequest request,Model model){
		//判断必要参数是否合法
		if(!"".equals(appid) && "login".equals(request_type) && !"".equals(redirect_uri)){
			App app = appService.getById(appid);
			//判断应用是否认证
			if(null != app){
				Map<String,String> cookies = CookieTool.ReadCookieMap(request);
				String loginSign = cookies.get("pt_login_sign");
				String timeout = cookies.get("pt_time");
				String acount = cookies.get("pt_acount");
				//判断COOKIE是否合法
				if(loginSign == null || timeout == null || acount == null){
					model.addAttribute("appid", appid);
					model.addAttribute("redirect_uri", redirect_uri);
					return "user/login";
				}
				String legalSign = SecretUtil.getMD5(acount=SecretUtil.decodeBase64(acount), AcountEnum.KEY.toString());
				if(legalSign.equals(loginSign)){
					Date date = new Date();
					long current = date.getTime();
					long interval = current - Long.valueOf(timeout);
					//COOKIE时间是否过期
					if(interval/1000 < Long.valueOf(AcountEnum.TIMEOUT.toString())){
						//再次校验用户是否合法
						User user = userService.queryByName(acount);
						if(user != null){
							model.addAttribute("appid", appid);
							model.addAttribute("redirect_uri", redirect_uri);
							model.addAttribute("response_type", "code");
							return "user/authorize";
						}
					}
					return "user/login";
				}
				
			}
			model.addAttribute("msg", "应用认证失败！");
			return "user/fail";
		}
		model.addAttribute("msg", "应用认证失败！");
		return "user/fail";
	}
	
	@RequestMapping(value="/apply",method=RequestMethod.GET)
	public String applyView(){
		return "manager/apply";
	}
	
	/***
	 * 应用接入
	 * @param appId 应用ID
	 * @param appSecret 应用密钥
	 * @param appName	应用名称
	 * @return
	 */
	@RequestMapping(value="/apply",method=RequestMethod.POST)
	public String apply(String appId,String appSecret,String appName,Model model){
		if(!"".equals(appId) && !"".equals(appSecret) && !"".equals(appName)){
			int result = appService.addApp(appId, appSecret, appName);
			if(result > 0){
				model.addAttribute("appName", appName);
				return "success";
			}
		}
		return "error";
	}
}
